package xcmg.device.service.safetyStock;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xcmg.device.dao.entity.safetyStock.ComSafetyStockInfo;
import xcmg.device.dao.entity.safetyStock.MaterialsSalesData;
import xcmg.device.dao.mapper.delivery.DeliveryNoteDetailMapper;
import xcmg.device.dao.mapper.safetyStock.ComSafetyStockInfoMapper;
import xcmg.device.dao.mapper.safetyStock.MaterialsSalesDataMapper;
import xcmg.device.infra.DateUtil;
import xcmg.device.service.vo.safetyStock.MonthSalesVO;
import yb.ecp.fast.infra.infra.log.LogHelper;

/**
 * @author wangyong
 */
@Service
public class MaterialsSalesDataService {


  @Autowired
  private MaterialsSalesDataMapper materialsSalesDataMapper;

  @Autowired
  private SafetyInventoryStrategy safetyInventoryStrategy;

  @Autowired
  private DeliveryNoteDetailMapper deliveryNoteDetailMapper;

  /**
   * 表示1个月前
   */
  private static final Integer LAST_MONTH_NO = 1;


  /**
   * 是否计算安全库存。0否，1是
   */
  private static final Short SAFETY_FLAG_YES = 1;

  /**
   * 获取公司所有需要计算安全库存的零件
   *
   * @param orgId
   * @return
   */
  public List<MaterialsSalesData> listCompanySalesData(String orgId) {

    return materialsSalesDataMapper.listAllByOrgId(orgId);
  }

  /**
   * 每月自动更新销售数据
   * @param materialsSalesData 零件出货量数据
   * @param planCode 方案编码
   */
  public void update(MaterialsSalesData materialsSalesData, String planCode, Date now) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
    // 每个月只能更新一次
    if (sdf.format(materialsSalesData.getUpdateTime()).equals(sdf.format(now))) {
      return;
    }
    materialsSalesData.setLastMonth13(materialsSalesData.getLastMonth12());
    materialsSalesData.setLastMonth12(materialsSalesData.getLastMonth11());
    materialsSalesData.setLastMonth11(materialsSalesData.getLastMonth10());
    materialsSalesData.setLastMonth10(materialsSalesData.getLastMonth9());
    materialsSalesData.setLastMonth9(materialsSalesData.getLastMonth8());
    materialsSalesData.setLastMonth8(materialsSalesData.getLastMonth7());
    materialsSalesData.setLastMonth7(materialsSalesData.getLastMonth6());
    materialsSalesData.setLastMonth6(materialsSalesData.getLastMonth5());
    materialsSalesData.setLastMonth5(materialsSalesData.getLastMonth4());
    materialsSalesData.setLastMonth4(materialsSalesData.getLastMonth3());
    materialsSalesData.setLastMonth3(materialsSalesData.getLastMonth2());
    materialsSalesData.setLastMonth2(materialsSalesData.getLastMonth());
    materialsSalesData.setLastMonth(countLastMonthSales(materialsSalesData.getOrgId(), materialsSalesData.getMaterialsNo(), now));
    BigDecimal val = calSalesVariance(materialsSalesData, planCode);
      materialsSalesData.setSalesVariance(val);

    materialsSalesData.setUpdateTime(now);
    try {
      materialsSalesDataMapper.update(materialsSalesData);

    } catch (Exception e) {
      LogHelper.fatal("Task>>>MaterialsSalesDataService#update is error.materialsNo:" + materialsSalesData.getMaterialsNo(), e);
    }
  }

  /**
   * 获取某个月零件出货量
   *
   * @param orgId
   * @param materialsNo
   * @param yearMonth
   * @return
   */
  private BigDecimal countLastMonthSales(String orgId, String materialsNo, Date yearMonth) {

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
    BigDecimal count = deliveryNoteDetailMapper.countOutAmountByMonth(orgId, materialsNo, dateFormat.format(yearMonth));
    return null == count ? BigDecimal.ZERO : count;
  }

  /**
   * 近13个月出货量与均需求量之间的方差
   *
   * @param materialsSalesData
   * @param planCode
   * @return
   */
  private BigDecimal calSalesVariance(MaterialsSalesData materialsSalesData, String planCode) {

    return safetyInventoryStrategy.calSalesVariance(materialsSalesData, planCode);
  }

  public List<MaterialsSalesData> listVariancesByOrgId(String orgId) {
    return materialsSalesDataMapper.listVariancesByOrgId(orgId);
  }


  /**
   * 根据零件号最后一位获取数据
   *
   * @param orgId
   * @param tailNum
   * @return
   */
  public List<MaterialsSalesData> listBytailNum(String orgId, String tailNum) {
    return materialsSalesDataMapper.listBytailNum(orgId, tailNum);
  }


  /**
   * 统计并生成最近13个月的出货数据
   *
   * @param orgId
   * @param materialsNo
   * @return
   * @throws Exception
   */
  public MaterialsSalesData gen13MonthSalesData(String orgId, String materialsNo, Date now, String planCode) throws Exception {
    // 前13个月到前上个月的数据
    Map<String, BigDecimal> monthSalesMap = getSalesMap(orgId, materialsNo, now, -13, -1);
    MaterialsSalesData materialsSalesDataDB = materialsSalesDataMapper.getByMaterialsNo(orgId, materialsNo);
    if (null != materialsSalesDataDB) {
      materialsSalesDataDB = fillSalesData(materialsSalesDataDB, monthSalesMap, now, planCode);
      materialsSalesDataMapper.update(materialsSalesDataDB);
      return materialsSalesDataDB;
    }
    MaterialsSalesData materialsSalesData = new MaterialsSalesData();
    materialsSalesData.setMaterialsNo(materialsNo);
    materialsSalesData.setOrgId(orgId);
    materialsSalesData = fillSalesData(materialsSalesData, monthSalesMap, now, planCode);
    materialsSalesDataMapper.insert(materialsSalesData);
    return materialsSalesData;
  }

  private MaterialsSalesData fillSalesData(MaterialsSalesData materialsSalesData, Map<String, BigDecimal> monthSalesMap, Date now, String planCode) {
    materialsSalesData.setLastMonth(getFromMap(monthSalesMap, getAfterYearMonStr(now, -1)));
    materialsSalesData.setLastMonth2(getFromMap(monthSalesMap, getAfterYearMonStr(now, -2)));
    materialsSalesData.setLastMonth3(getFromMap(monthSalesMap, getAfterYearMonStr(now, -3)));
    materialsSalesData.setLastMonth4(getFromMap(monthSalesMap, getAfterYearMonStr(now, -4)));
    materialsSalesData.setLastMonth5(getFromMap(monthSalesMap, getAfterYearMonStr(now, -5)));
    materialsSalesData.setLastMonth6(getFromMap(monthSalesMap, getAfterYearMonStr(now, -6)));
    materialsSalesData.setLastMonth7(getFromMap(monthSalesMap, getAfterYearMonStr(now, -7)));
    materialsSalesData.setLastMonth8(getFromMap(monthSalesMap, getAfterYearMonStr(now, -8)));
    materialsSalesData.setLastMonth9(getFromMap(monthSalesMap, getAfterYearMonStr(now, -9)));
    materialsSalesData.setLastMonth10(getFromMap(monthSalesMap, getAfterYearMonStr(now, -10)));
    materialsSalesData.setLastMonth11(getFromMap(monthSalesMap, getAfterYearMonStr(now, -11)));
    materialsSalesData.setLastMonth12(getFromMap(monthSalesMap, getAfterYearMonStr(now, -12)));
    materialsSalesData.setLastMonth13(getFromMap(monthSalesMap, getAfterYearMonStr(now, -13)));
    materialsSalesData.setUpdateTime(now);
    materialsSalesData.setSafetyFlag(SAFETY_FLAG_YES);
    materialsSalesData.setSalesVariance(calSalesVariance(materialsSalesData, planCode));
    return materialsSalesData;
  }


  /**
   * 更新某个月的销售数据。前期很多销售数据是手动导入，部分月份需要用导入的数据，部分需要用系统记录的数据，主要是为了支持这种情况，将导入的数据中某月出货数据刷新为系统的数据
   *
   * @param planCode 方案编码
   * @param monthAfterNo 当前月前monthAfterNo个月
   * @throws Exception
   */
  public void genSpecialMonthSalesData(MaterialsSalesData materialsSalesData, String planCode, Integer monthAfterNo) throws Exception {
      Date now = new Date();
      // 取某个月的出货数据
      Map<String, BigDecimal> monthSalesMap = getSalesMap(materialsSalesData.getOrgId(), materialsSalesData.getMaterialsNo(), now, -monthAfterNo, -monthAfterNo);
      if (LAST_MONTH_NO.equals(monthAfterNo)) {
        materialsSalesData.setLastMonth(getFromMap(monthSalesMap, getAfterYearMonStr(now, -1)));
      } else {
        Method method = materialsSalesData.getClass().getMethod("setLastMonth" + String.valueOf(monthAfterNo), BigDecimal.class);
        method.invoke(materialsSalesData, getFromMap(monthSalesMap, getAfterYearMonStr(now, -monthAfterNo)));
      }
      //此操作为临时功能，不刷新更新时间，因为定时任务会根据updateTime来识别本月是否执行过
//      materialsSalesData.setUpdateTime(now);
      materialsSalesData.setSalesVariance(calSalesVariance(materialsSalesData, planCode));
      materialsSalesDataMapper.update(materialsSalesData);
  }

  private Map<String, BigDecimal> getSalesMap(String orgId, String materialsNo, Date now, Integer afterMonthStart, Integer afterMonthEnd) {
    List<MonthSalesVO> monthSales = deliveryNoteDetailMapper.countOutByMonthInterval(orgId, materialsNo,
        DateUtil.getMonthStartTime(DateUtil.getAfterMonthDate(now, afterMonthStart)), DateUtil.getMonthEndTime(DateUtil.getAfterMonthDate(now, afterMonthEnd)));
    Map<String, BigDecimal> monthSalesMap = new HashMap<>();
    if (CollectionUtils.isEmpty(monthSales)) {
      return monthSalesMap;
    }
    for (MonthSalesVO salesVO : monthSales) {
      monthSalesMap.put(salesVO.getYearMonth(), salesVO.getSalesNum());
    }
    return monthSalesMap;
  }

  /**
   * 获取n个月后的时间，yyyy-mm格式
   *
   * @param date
   * @param n
   * @return
   */
  private String getAfterYearMonStr(Date date, int n) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
    return sdf.format(DateUtil.getAfterMonthDate(date, n));
  }

  private BigDecimal getFromMap(Map<String, BigDecimal> monthSalesMap, String key) {
    if (null == monthSalesMap || monthSalesMap.size() == 0 || null == monthSalesMap.get(key)) {
      return BigDecimal.ZERO;
    }
    return monthSalesMap.get(key);
  }
}
